<template>
  <div class="app">
    <div class="top">
      <div class="avatar"></div>
      <div class="select">
        <input placeholder="电击小子" v-model="input" @keydown.enter="source"/>
      </div>
      <div class="info"></div>
    </div>
    <div class="menu">
      <tabs-view/>
    </div>
    <div class="warp">
      <div class="warp-item">
        <div class="images">
          <img :src="image" alt="" v-for="item in 10" :key="item" ref="warps" class="is-warp"/>
        </div>
      </div>
      <div class="i">

      </div>
    </div>
    <div class="item" ref="itemVideo" @scroll="handleScroll">
      <!-- 首屏骨架（只在第一次加载时显示） -->
      <div v-if="loadingInitial" class="item">
        <div class="item-i skeleton" v-for="n in 20" :key="'skl-initial-'+n">
          <div class="skeleton-img"></div>
          <div class="skeleton-text"></div>
          <div class="skeleton-tag"></div>
        </div>
      </div>

      <!-- 正常列表 + 底部骨架 -->
      <div v-else class="item" ref="itemVideo" @scroll.passive="handleScroll">
        <div
            class="item-i"
            v-for="(item,index) in videos"
            :key="item.vodId ?? index"
            @click="toPlay(item)">
          <img :src="item.vodPic" :alt="item.vodName"/>
          <span class="name">{{ item.vodName }}</span>
          <div class="tag" v-html="tag(item.vodTag)"/>
        </div>

        <!-- 翻页加载中的骨架：仅出现在底部，不会重建整个列表 -->
        <div v-if="loadingMore" class="item-i skeleton" v-for="n in 20" :key="'skl-more-'+n">
          <div class="skeleton-img"></div>
          <div class="skeleton-text"></div>
          <div class="skeleton-tag"></div>
        </div>

        <div v-if="!hasMore && videos.length" class="list-end">—— 没有更多了 ——</div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import {onMounted, ref} from 'vue'
import image from '@/assets/index.jpg'
import {listVideo, queryVideo} from '@/api/index'
import router from '@/router'
import {isNull} from '@/utils'
import tabsView from '@/components/tabs/index.vue'
import {loading} from '@/components/loading'
import {routerStatus} from "@/pinia";

onMounted(async () => {
  await initVideo()
})

const input: any = ref<any>('')
const warps: any = ref<any>('')
const videos = ref<any>([])
const itemVideo = ref<HTMLElement>()
const loadingInitial = ref<boolean>(true)
const loadingMore = ref<boolean>(false)
const isFetching = ref<boolean>(false)
const hasMore = ref<boolean>(true)
const pageNum = ref<number>(1)
const pageSize = 10
const isSelectPage = ref<boolean>(false)

const tag = (item: string) => (isNull(item) ? '<span>暂无分类</span>' : item.split(',').map(i => (`<p>${i}</p>`)).join(' '))

const initVideo = async () => {
  try {
    loadingInitial.value = true
    const res = await listVideo({pageNum: 1, pageSize: 20})
    videos.value = res?.rows ?? []
    hasMore.value = (res?.rows?.length ?? 0) >= 20
    pageNum.value = 1
    console.log(videos.value)
  } catch (error) {
    await initVideo()
  } finally {
    loadingInitial.value = false
  }
}

const loadMore = async () => {
  if (isFetching.value || !hasMore.value) return
  isFetching.value = true
  loadingMore.value = true
  try {
    pageNum.value += 1
    const res = await listVideo({pageNum: pageNum.value, pageSize})
    const rows = res?.rows ?? []
    if (!rows.length) {
      hasMore.value = false
    } else {
      videos.value.push(...rows)
      if (rows.length < pageSize) hasMore.value = false
    }
  } finally {
    loadingMore.value = false
    isFetching.value = false
  }
}

const loadMoreSelect = async () => {
  if (isFetching.value || !hasMore.value) return
  isFetching.value = true
  loadingMore.value = true
  try {
    pageNum.value += 1
    const res = await queryVideo({pageNum: pageNum.value, pageSize}, input.value)
    const rows = res?.rows ?? []
    if (!rows.length) {
      hasMore.value = false
    } else {
      videos.value.push(...rows)
      if (rows.length < pageSize) hasMore.value = false
    }
  } finally {
    loadingMore.value = false
    isFetching.value = false
  }
}

const handleScroll = (e: Event) => {
  if (isSelectPage.value) {
    const el = e.target as HTMLElement
    // 接近底部阈值 20px，避免严格相等触发不了
    const nearBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - 20
    if (nearBottom) loadMoreSelect()
  } else {
    const el = e.target as HTMLElement
    // 接近底部阈值 20px，避免严格相等触发不了
    const nearBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - 20
    if (nearBottom) loadMore()
  }
}


const toPlay = async (item: any) => {
  await router.push({name: 'play', query: item})
}

const source = async () => {
  // 判断是否是搜索模式
  isSelectPage.value = input.value.trim() !== ''

  // 每次搜索/切换模式要重置分页和状态
  pageNum.value = 1
  hasMore.value = true
  videos.value = []
  loadingInitial.value = true

  try {
    routerStatus().setLoading(true)
    loading(isSelectPage.value ? '请求搜索资源中....' : '加载视频中...')

    const api = isSelectPage.value ? queryVideo : listVideo
    const res = isSelectPage.value
        ? await api({ pageNum: 1, pageSize }, input.value)
        : await api({ pageNum: 1, pageSize })

    videos.value = res?.rows ?? []
    hasMore.value = (res?.rows?.length ?? 0) >= pageSize
  } catch (e) {
    console.error(e)
  } finally {
    routerStatus().setLoading(false)
    loadingInitial.value = false
  }
}

</script>

<style lang="scss" scoped>
.app {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: center;
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  padding: 5px 0;

  .top {
    //border: 1px solid red;
    width: 100%;
    height: 60px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    box-sizing: border-box;
    padding: 0 10px;

    .avatar {
      background: var(--theme);
      //border: 1px solid red;
      width: 50px;
      height: 50px;
      border-radius: 50%;
      display: flex;
      justify-content: center;
      align-items: center;
      object-fit: cover;
      object-position: center;
    }

    .select {
      border: 2px solid var(--border-color);
      width: calc(100% - 50px - 50px);
      height: 80%;
      margin: 0 10px;
      box-sizing: border-box;
      display: flex;
      padding-left: 10px;
      border-radius: 30px;
      overflow: hidden;

      input {
        width: 100%;
        height: 100%;
        outline: none; /* 去除外边框 */
        padding: 0; /* 去除内边距 */
        margin: 0; /* 去除外边距 */
        font: inherit; /* 继承父元素的字体样式 */
      }
    }

    .info {
      border: 1px solid red;
      width: 35px;
      height: 35px;
      display: flex;
      justify-content: center;
      align-items: center;
      box-sizing: border-box;
      object-position: center;
      object-fit: cover;
    }
  }

  .menu {
    //border: 1px solid red;
    margin: 10px 0;
    width: 100%;
    height: 140px;
    font-size: 14px;
    display: flex;
    justify-content: flex-start;
    align-items: center;
    //overflow: scroll;
    white-space: nowrap;
    padding: 5px 0;

    @media screen and (min-width: 992px) {
      justify-content: center;
      //border: 1px solid red;
    }
  }

  .warp {
    //border: 1px solid red;
    width: 100%;
    height: 250px;
    position: relative;

    @media screen and (min-width: 992px) {
      height: 320px;
    }

    .warp-item {
      width: 100%;
      height: 100%;
      object-fit: cover;
      cursor: pointer;
      box-sizing: border-box;

      .images {
        width: 100%;
        height: 100% !important;
        z-index: 1;
        top: 0;
        left: 0;
        display: flex;
        flex-wrap: nowrap;
        gap: 5px;
        box-sizing: border-box;
        padding: 2px;
        position: relative;
        overflow: hidden;

        img {
          width: 100%;
          height: 100%;
          z-index: inherit;
          border-radius: 10px;
        }

        .is-warp {
          display: block;
          animation: slideIn 3s ease-in-out forwards infinite;

          @keyframes slideIn {
            0% {
              transform: translateX(-100%);
              background: linear-gradient(90deg, rgba(255, 0, 150, 0) 0%, rgba(0, 204, 255, 1) 100%);
            }
            50% {
              transform: translateX(0);
              background: linear-gradient(90deg, rgba(255, 0, 150, 0.4) 0%, rgba(0, 204, 255, 0.6) 100%);
            }
            100% {
              transform: translateX(0);
              background: linear-gradient(90deg, rgba(255, 0, 150, 0) 0%, rgba(0, 204, 255, 0) 100%);
            }
          }
        }
      }
    }

    .i {
      border: 1px solid red;
      position: absolute;
      width: 100px;
      height: 10px;
      bottom: 10px;
      right: 5px;
      z-index: 9;
      display: flex;
    }

  }

  .item {
    //margin: 10px 0;
    //border: 1px solid red;
    width: 100%;
    height: calc(100% - 10px - 250px - 30px - 60px - 20px);
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    overflow: auto;
  }

  .skeleton {
    border: 1px solid var(--theme);
    height: 350px;
    width: calc(100% / 4);
    margin: 7px;
    border-radius: 5px;
    flex: 0 1 calc(50% - 14px);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;

    .skeleton-img,
    .skeleton-text,
    .skeleton-tag {
      background: linear-gradient(90deg, #eee 25%, #f5f5f5 50%, #eee 75%);
      background-size: 200% 100%;
      animation: shimmer 1.5s infinite;
      border-radius: 5px;
      margin: 5px;
    }

    .skeleton-img {
      flex: none;
      width: 100%;
      height: 300px;
    }

    .skeleton-text {
      height: 20px;
      width: 70%;
    }

    .skeleton-tag {
      height: 20px;
      width: 50%;
    }
  }

  @keyframes shimmer {
    0% {
      background-position: -200% 0;
    }
    100% {
      background-position: 200% 0;
    }
  }

  .item-i {
    padding: 1px;
    border: 1px solid var(--theme);
    height: 350px;
    width: calc(100% / 4);
    margin: 7px;
    border-radius: 5px;
    flex: 0 1 calc(50% - 14px);
    overflow: hidden;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;

    img {
      //border: 1px solid red;
      width: 100%;
      height: calc(100% - ((100% - 300px) / 2) - 20px);
    }

    .name, .tag {
      //border: 1px solid red;
      width: 100%;
      height: calc((100% - 300px) / 2);
      font-size: 12px;
      display: flex;
      justify-content: flex-start;
      align-items: center;
    }

    .tag {
      //border: 1px solid red;
      display: flex;
      flex-wrap: wrap;
      justify-content: flex-start;
      align-items: center;
      overflow: scroll;

      *:nth-child(1) {
        margin: 0;
      }

      * {
        //border: 1px solid red;
        width: auto;
        height: 90%;
        background: rgb(64, 197, 241);
        color: white;
        padding: 0 5px;
        border-radius: 5px;
        margin: 5px;
        display: flex;
        align-items: center;
        justify-content: center;
      }
    }

    &:hover {
      cursor: pointer;

      img {
        transform: scale(1.05);
        animation: rotateYAnim 1s ease-in-out forwards;
      }

      @keyframes rotateYAnim {
        0% {
          transform: rotateY(0deg);
        }
        50% {
          transform: rotateY(180deg);
        }
        100% {
          transform: rotateY(360deg);
        }
      }
    }

  }

  @media screen and (min-width: 992px) {
    .item {
      justify-content: center;
      align-items: start;
      height: calc(100%);
      //border: 1px solid red;
    }
    .warp {
      display: none;
    }
    .item-i {
      max-width: 250px;
      max-height: 350px;
      flex: 0 1 auto;
    }
  }

  @media screen and (max-width: 430px) {
    .item-i {
      width: 180px;
      //height: 200px;
    }
  }

}
</style>
